// 每天至少一个面试题 

/* @ 实现一个 instanceOf
概念解释：
    instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

语法：  
    object instanceof constructor
    object --> 某个实例对象   constructor --> 某个构造函数
    -- 用来检测  constructor.prototype 是否存在于参数  object 的原型链上。

举例：
    // 定义构造函数
    function C () {}
    function D () {}
    var o = new C()
    console.log(o instanceof C, o.__proto__ === C.prototype) // true，true C.prototype 在 o 的原型链上
    console.log(o instanceof D, o.__proto__ === D.prototype) // false，false D.prototype 不在 o 的原型链上
    console.log(o instanceof Object, o.__proto__.__proto__ === Object.prototype) // true true
    C.prototype = {}
    var o2 = new C()
    console.log(o2 instanceof C) // true
    console.log(o instanceof C) // false，C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
    D.prototype = new C() // 继承
    var o3 = new D()
    console.log(o3 instanceof D) // true
    console.log(o3 instanceof C) // true 因为 C.prototype 现在在 o3 的原型链上

一些容易出错的点：
    var simpleStr = "This is a simple string"; 
    var myString  = new String();
    var newStr    = new String("String created with constructor");
    var myDate    = new Date();
    var myObj     = {};
    var myNonObj  = Object.create(null);
    
    simpleStr instanceof String; // 返回 false, simpleStr并不是对象
    myString  instanceof String; // 返回 true
    newStr    instanceof String; // 返回 true
    myString  instanceof Object; // 返回 true
    
    myObj instanceof Object;    // 返回 true, 尽管原型没有定义
    ({})  instanceof Object;    // 返回 true, 同上
    myNonObj instanceof Object; // 返回 false, 一种创建非 Object 实例的对象的方法
    
    myString instanceof Date; // 返回 false
    
    myDate instanceof Date;     // 返回 true
    myDate instanceof Object;   // 返回 true
    myDate instanceof String;   // 返回 false

instanceof能否判断基本数据类型？
    class PrimitiveNumber {
        static [Symbol.hasInstance](x) {
            return typeof x === 'number'
        }
    }
    console.log(111 instanceof PrimitiveNumber) // true
    // 自定义instanceof行为的一种方式，
    // 这里将原有的instanceof方法重定义，换成了typeof，因此能够判断基本数据类型。

**/
    // version 1
    function instanceOfV1(obj, ConstructoR) {
        let proto = obj.__proto__; // 实例的隐式原型
        let prototype = ConstructoR.prototype // 类的原型
        while(true) { // --> 1)
            if(proto === null) return false
            if(proto === prototype) return true
            proto = proto.__proto__; // --> 2)
            /* 1)+2) --> 深层遍历实例的隐式原型链，检测构造器原型是否出现在实例的原型链上。*/ 
        }
    }
    // version 2
    function instanceOfV2 (obj, ConstructoR) {
        // 基本数据类型直接返回 false
        if (typeof obj !== 'object' || obj === null) return false
        // getProtypeOf是Object对象自带的一个方法，能够拿到参数的原型对象
        let proto = Object.getPrototypeOf(obj)
        while (true) {
            // 查找到尽头，还没找到
            if (proto == null) return false
            // 找到相同的原型对象
            if (proto == ConstructoR.prototype) return true
            proto = Object.getPrototypeOf(proto);
        }
    }









